class Hd{
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECT = "reject";
    constructor(executor){
        this.status = Hd.PENDING;
        this.value = null;
        this.callbacks = [];
        try {
            executor(this.resolve.bind(this), this.reject.bind(this));
        } catch (error) {
            this.reject(error);                                 //处理变量不存在等异常
        }
    }

    resolve(value){
        if(this.status == Hd.PENDING){                          //状态一旦修改了就不可以再次修改
            this.status = Hd.FULFILLED;
            this.value = value;
            setTimeout(() => {                                  //让任务队列中函数实现异步
                this.callbacks.map(callback => {                //任务队列中要执行的函数
                    callback.onFulfilled(value);
                })
            })
        }
    }

    reject(reason){
        if(this.status == Hd.PENDING){                          //状态一旦修改了就不可以再次修改
            this.status = Hd.REJECT;
            this.value = reason;
            setTimeout(() => {                                  //让任务队列中函数实现异步
                this.callbacks.map(callback => {                //任务队列中要执行的函数
                    callback.onRejected(reason);
                })
            })
        }
    }

    then(onFulfilled,onRejected){
        if(typeof onFulfilled != 'function'){                   //如果不传也不会报错
            onFulfilled = () => this.value;                     //实现then的穿透
        }

        if(typeof onRejected != 'function'){                    //如果不传也不会报错
            onRejected = () => this.value;                      //实现then的穿透
        }

        let promise =  new Hd((resolve,reject) => {             //then里面返回一个新的Hd对象，实现链式操作
            if(this.status == Hd.PENDING){                      //如果是准备状态，将要执行的函数放到数组中
                this.callbacks.push({
                    onFulfilled : value => {
                        this.parser(promise,onFulfilled(value),resolve, reject);
                    },
                    onRejected : value => {
                        this.parser(promise,onRejected(value),resolve, reject);
                    }
                });
            }
    
            if(this.status == Hd.FULFILLED){                    //如果状态改变，执行对应的方法
                setTimeout(() =>{                               //setTimeout将任务放到下一次执行，实现异步
                    this.parser(promise,onFulfilled(this.value),resolve, reject);
                })
            }
    
            if(this.status == Hd.REJECT){                       //如果状态改变，执行对应的方法
                setTimeout(() => {                              //setTimeout将任务放到下一次执行，实现异步
                    this.parser(promise,onRejected(this.value),resolve, reject);
                })
            }
        });

        return promise;
    }

    parser(promise,result,resolve,reject){
        if(promise == result){                                 //不可以调用自己
            throw new TypeError("不可以调用本身");
        }
        try {                                                  //处理要执行的函数中任务不存在等异常
            if(result instanceof Hd){                          //判断返回的是常量还是一个Hd对象
                result.then(resolve, reject);                  //如果是Hd对象，返回对象中的状态和值
            }else{
                resolve(result);                               //如果不是Hd对象，下一次的then的状态为成功，并保留这一次返回的值
            }                    
        } catch (error) {
            reject(error);                                     //这一次的错误，放到下一次的错误中处理
        }
    }

    static resolve(value){
        return new Hd((resolve,reject) => {
            if(value instanceof Hd){
                value.then(resolve,reject);
            }else{
                resolve(value);
            }
        })
    }

    static reject(value){
        return new Hd((resolve,reject) => {
            if(value instanceof Hd){
                value.then(resolve,reject);
            }else{
                reject(value);
            }
        })
    }

    static all(promises){
        const values = [];
        return new Hd((resolve,reject) => {
            promises.forEach(promise => {
                promise.then(
                    value => {
                        values.push(value);
                        if(values.length == promises.length){
                            resolve(values);
                        }
                    },
                    reason => {
                        reject(reason);
                    }
                );
            })
        })
    }

    static race(promises){
        return new Hd((resolve,reject) => {
            promises.map(promise => {
                promise.then(
                    value => {
                        resolve(value);
                    },
                    reason => {
                        reject(reason);
                    }
                )
            })
        })
    }
}